
#include <iostream>
#include <string>

#include <stdio.h>
#include <ctype.h>


#define BUF_SIZE 256

void work(FILE *in, FILE *out);

int main(int argc, char *argv[]) 
{
	if (argc < 2) {
		std::cout << "USAGE: tokenstable <input.h> [<out.c>]" << std::endl;
		return 0;
	}

	FILE *infile = fopen(argv[1], "rt");
	if (infile == 0) {
		std::cerr << "ERROR: unable to open file \"" << argv[1] << "\"" << std::endl;
		return 1;
	}

	std::string outname;
	if (argc < 3) {
		outname = argv[1];
		if (outname.size() > 2) {
			std::string ext = outname.substr(outname.size() - 2);
			if (ext == ".h" || ext == ".H") {
				outname.erase(outname.size() - 2);
			}
		}
		outname.append(".tk.c");
	} else {
		outname = argv[2];
	}

	FILE *outfile = fopen(outname.c_str(), "wt");
	if (outfile == 0) {
		std::cerr << "ERROR: unable to write file \"" << outname << "\"" << std::endl;
		fclose(infile);
		return 1;
	}

	work(infile, outfile);

	fclose(infile);
	fclose(outfile);

	return 0;
}


static const std::string DEFINE = "define";


void work(FILE *in, FILE *out) 
{
	char buff[BUF_SIZE];

	fprintf(out, "struct {\n\tint Id;\n\tchar *Name;\n} tokens_table[] = {\n");

	while (fgets(buff, BUF_SIZE - 1, in)) 
	{
		std::string buffstr = buff;

		if (buffstr.empty()) continue;
		if (buffstr[buffstr.size() - 1] == '\n') buffstr.erase(buffstr.size() - 1);
		if (buffstr.empty()) continue;
		if (buffstr[0] != '#') continue;
		buffstr.erase(0, 1);

		while (!buffstr.empty() && isspace(buffstr[0])) buffstr.erase(0, 1);
		if (buffstr.empty()) continue;

		if (buffstr.substr(0, DEFINE.size()) != DEFINE) continue;
		buffstr.erase(0, DEFINE.size());

		while (!buffstr.empty() && isspace(buffstr[0])) buffstr.erase(0, 1);
		if (buffstr.empty()) continue;

		size_t index = buffstr.find_first_of(" \t");
		std::string name = buffstr.substr(0, index);
		buffstr.erase(0, index);

		while (!buffstr.empty() && isspace(buffstr[0])) buffstr.erase(0, 1);
		if (buffstr.empty()) continue;

		index = buffstr.find_first_of(" \t");
		std::string value = buffstr.substr(0, index);

		if (value.find_first_not_of("0123456789") != std::string::npos) continue;

		name = '\"' + name + '\"';

		fprintf(out, "\t{ %-30s, %-30s },\n", value.c_str(), name.c_str());
	}
	fprintf(out, "\t{ %-30s, %-30s },\n", "-1", "\"\"");
	fprintf(out, "};\n");
}
